package ngat.oss;

import ngat.astrometry.Position;
import ngat.instrument.*;
import ngat.util.*;
import ngat.util.logging.*;
import ngat.phase2.*;

import java.io.*;
import java.util.*;
import java.lang.reflect.*;

/** Holds some current telescope settings for use in scheduling. 
 * The following information is required to be stored.
 * AUTOGUIDER                     - Whether or not currently online.
 * TELESCOPE LAT, LONG and HEIGHT - the telescope location.
 *           AZ_LIMITS            - telescope azimuth limits +/-.
 * INSTRUMENTS                    - A list (map) of instruments by name.
 * Foreach INSTRUMENT:
 *    NAME    - The name/id of the Instrument.
 *    CONFIG  - The instrument's current configuration.
 *    STATUS  - Whether it is currently online.
 *    CURRENT - Whether it is currently selected.
 * 
 *
 * $Id: TelescopeStatus.java,v 1.1 2006/11/27 08:45:00 snf Exp $
 *
 */
public class TelescopeStatus implements Logging {

    public static final String CLASS = "TelescopeInfo";

    public static final String RAT_CAM_NAME   = "RATCAM";

    public static final String SUPIR_CAM_NAME = "SUPIRCAM";

    public static final String MES_SPEC_NAME  = "MESSPEC";

    public static final String NUV_SPEC_NAME  = "NUVSPEC";

    private static Logger errorLog = LogManager.getLogger(ERROR);

    private static Logger logger =  LogManager.getLogger(TRACE);

    /** Set true if the autoguider is currently available.*/
    private static boolean autoguiderAvailable = false;

    public static void     setAutoguiderAvailable(boolean in) { autoguiderAvailable = in; } 

    public static boolean  isAutoguiderAvailable() { return autoguiderAvailable; }


    /** The set of instruments available.*/
    private static Map instruments = new HashMap();

    /** The set of instrument config classes available.*/
    private static Map cfgMap = new HashMap();
    
    /** Currently in use Instrument.*/
    private static Instrument currentInstrument = null;
    
    public  static Instrument getCurrentInstrument() { return currentInstrument; }
    
    public  static void       setCurrentInstrument(Instrument in) { currentInstrument = in; }


    /** Current  (latest) Instrument configuration for currently selected Instrument.*/
    private static InstrumentConfig currentInstrumentConfig = null;
    
    public  static InstrumentConfig getCurrentInstrumentConfig() { return  currentInstrumentConfig;}
    
    public  static void             setCurrentInstrumentConfig(InstrumentConfig in) { currentInstrumentConfig = in;}       
    /** Current  (latest) Telescope configuration.*/
    private static TelescopeConfig currentTelescopeConfig = null;
     
    public  static void            setCurrentTelescopeConfig(TelescopeConfig in) {currentTelescopeConfig = in;}

    public  static TelescopeConfig getCurrentTelescopeConfig() { return currentTelescopeConfig;}
    

    /**Current  (latest) Pipeline Config.*/
    private static PipelineConfig currentPipelineConfig = null;
    
    public  static PipelineConfig getCurrentPipelineConfig() { return currentPipelineConfig;}
    
    public  static void           setCurrentPipelineConfig(PipelineConfig in) {currentPipelineConfig = in;}
    
    /** Current (latest) Telescope Azimuth Position. */
    private static double telescopeAzimuth = 0.0;

    public static void      setTelescopeAzimuth(double in) { telescopeAzimuth = in;}

    public static double    getTelescopeAzimuth() { return telescopeAzimuth;}

    /** Current (latest) Telescope Altitude Position. */
    private static double telescopeAltitude = 0.0;

    public static void      setTelescopeAltitude(double in) { telescopeAltitude = in;}

    public static double    getTelescopeAltitude() { return telescopeAltitude;}


    /** Azimuth negative limit (rads).*/
    private static double azNegLimit = 0.0;

    public static void      setAzNegLimit(double in) { azNegLimit = in;}

    public static double    getAzNegLimit() { return azNegLimit;}
  
    /** Azimuth postive limit (rads).*/
    private static double azPosLimit = 0.0;

    public static void      setAzPosLimit(double in) { azPosLimit = in;}

    public static double    getAzPosLimit() { return azPosLimit;}
  
    /** Altitude negative limit (rads).*/
    private static double altLowLimit = 0.0;

    public static void      setAltLowLimit(double in) { altLowLimit = in;}

    public static double    getAltLowLimit() { return altLowLimit;}
  
    /** Altimuth postive limit (rads).*/
    private static double altHighLimit = 0.0;

    public static void      setAltHighLimit(double in) { altHighLimit = in;}

    public static double    getAltHighLimit() { return altHighLimit;}
  
    /** Rot negative limit (rads).*/
    private static double rotNegLimit = 0.0;

    public static void      setRotNegLimit(double in) { rotNegLimit = in;}

    public static double    getRotNegLimit() { return rotNegLimit;}
  
    /** Rot postive limit (rads).*/
    private static double rotPosLimit = 0.0;

    public static void      setRotPosLimit(double in) { rotPosLimit = in;}

    public static double    getRotPosLimit() { return rotPosLimit;}
  



   
    // START BOLLOCKS
    public static CCD                 RATCAM   = new CCD(RAT_CAM_NAME);
    
    public static IRCam               SUPIRCAM = new IRCam(SUPIR_CAM_NAME);
    
    public static HiResSpectrograph   MESSPEC  = new HiResSpectrograph(MES_SPEC_NAME);
    
    public static LowResSpectrograph  NUVSPEC  = new LowResSpectrograph(NUV_SPEC_NAME);
    // END  BOLLOCKS


    /** Returns a reference to the named Instrument or null if no such instrument
     * is known to the OSS.*/
    public static Instrument getInstrument(String name) {
	if (instruments.containsKey(name))
	    return (Instrument)instruments.get(name);
	return null;
    }

    /** Returns a reference to the Instrument for which the Config is defined, 
     *or null if no such instrument.*/
    public static Instrument getInstrumentFor(InstrumentConfig config) {
	Class clazz = config.getClass();
	if (cfgMap.containsKey(clazz))
	    return (Instrument)cfgMap.get(clazz);	
	return null;
    }

   
  
    /** Configure the available instruments using the data in their default
     * database config files and semester property files.
     * @exception IOException If any I/O error occurs while loading a config.
     * @exception IllegalArgumentException If any parameters cannot be parsed
     * or are missing from a conf ig file.*/
    public static void configureInstruments(File file) 
	throws IOException, IllegalArgumentException { 
	
	ConfigurationProperties config = new ConfigurationProperties();
	config.load(new FileInputStream(file));

	// Entries like: { <shortId> .ID }
	// <shortId> can be e.g. inst.1 inst.2 etc or abbreviations.

	Enumeration e = config.propertyNames();
	while (e.hasMoreElements()) {

	    String key = (String)e.nextElement();	  
	    if (key.indexOf(".ID") == -1) continue;
	    
	    String instId = config.getProperty(key);

	    String desc =  config.getProperty(instId+".description");

	    // Now look for: { <instID> .class, .config.file etc }
	    String instClazz = config.getProperty(instId+".class");
	    if (instClazz == null)
		throw new IllegalArgumentException("Instrument: "+instId+" - No class defined.");

	    String configFileName = config.getProperty(instId+".config.file");
	    File configFile = new File(configFileName);
	    
	    if (! configFile.exists())
		throw new IllegalArgumentException("Instrument: "+instId+
						   " Config File: "+configFileName+
						   " - No such file.");	    

	    String configClazz =  config.getProperty(instId+".config.class");
	    if (configClazz == null)
		throw new IllegalArgumentException("Instrument: "+instId+" - No config class defined.");
	    
	    Class cfgClass = null;
	    try {
		cfgClass = Class.forName(configClazz);
	    } catch (Exception ex) {
		throw new IllegalArgumentException("Instrument: "+instId+
						   " - Unable to identify config class: "+configClazz+
						   " : "+ex);
	    }

	    // Create the Instance of this Instrument.
	    Instrument instObj = null;
	    try {
		Class instClass = Class.forName(instClazz);		
		Constructor con = instClass.getConstructor(new Class[]{String.class});		
		
		instObj = (Instrument)con.newInstance(new Object[]{instId});
		// Store the instrument and its configuration class.
		instruments.put(instId, instObj);
		cfgMap.put(cfgClass, instObj);

		logger.log(1, CLASS, "", "configure",
			   "\nCreated and stored Instrument description: "+
			   "\n\tInstrument ID:    "+instId+
			   "\n\tClass:            "+instClazz+
			   "\n\tConfig Class:     "+configClazz+
			   "\n\tConfig File:      "+configFile.getPath()+
			   "\n\tDescription:      "+desc);	
		System.err.println("*********************"+
				   "\nCreated and stored Instrument description: "+
				   "\n\tInstrument ID:    "+instId+
				   "\n\tClass:            "+instClazz+
				   "\n\tConfig Class:     "+configClazz+
				   "\n\tConfig File:      "+configFile.getPath()+
				   "\n\tDescription:      "+desc);
	    } catch (Exception ex) {
		throw new IllegalArgumentException("Generating instrument class for: "+instId+" : "+ex);
	    }
	    
	    // Try Configure/setup the Instrument.  
	    instObj.configure(configFile);
	    
	    // Load a Default InstConfig.
	    instObj.loadConfig();  
	    System.err.println("Instrument: "+instId+" Configured:"+
			       instObj.getConfig("TEST"));
	}
    }
   
}

/** $Log: TelescopeStatus.java,v $
/** Revision 1.1  2006/11/27 08:45:00  snf
/** Initial revision
/**
/** Revision 1.1  2006/11/27 08:37:05  snf
/** Initial revision
/**
/** Revision 1.4  2001/02/23 18:46:58  snf
/** Added stuff.
/**
/** Revision 1.3  2001/01/09 18:49:42  snf
/** Corrections.
/**
/** Revision 1.2  2000/11/29 12:55:41  snf
/** Telescope status information.
/**
/** Revision 1.1  2000/11/22 14:14:10  snf
/** Initial revision
/** */
